package com.mobilezu.mobile.pushserver.xmpp.push;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.QName;
import org.xmpp.packet.IQ;
import com.mobilezu.mobile.pushserver.model.PushData;
import com.mobilezu.mobile.pushserver.model.PushUser;
import com.mobilezu.mobile.pushserver.service.PushDataService;
import com.mobilezu.mobile.pushserver.service.PushUserService;
import com.mobilezu.mobile.pushserver.service.ServiceManager;
import com.mobilezu.mobile.pushserver.service.UserNotFoundException;
import com.mobilezu.mobile.pushserver.util.Config;
import com.mobilezu.mobile.pushserver.util.Constants;
import com.mobilezu.mobile.pushserver.xmpp.presence.PresenceManager;
import com.mobilezu.mobile.pushserver.xmpp.session.ClientSession;
import com.mobilezu.mobile.pushserver.xmpp.session.SessionManager;

public class NotificationManager {

	public static final String NOTIFICATION_NAMESPACE = "androidpn:iq:notification";
	private final Log log = LogFactory.getLog(getClass());
	private SessionManager sessionManager;
	private PushDataService pushDataService;
	private PushUserService pushUserService;
	private PresenceManager presenceManager;

	/**
	 * ������.
	 */
	public NotificationManager() {
		sessionManager = SessionManager.getInstance();
		pushDataService = ServiceManager.getPushDataService();
		pushUserService = ServiceManager.getPushUserService();
		presenceManager = new PresenceManager();
	}

	/**
	 * ���͸������û�
	 * 
	 * @param apiKey
	 * @param sendName
	 * @param message
	 * @param uri
	 */
	public void sendToAllUsers(String apiKey, String sendUsername,
			String sendName, String message, String uri) {
		log.debug("sendToAllUsers()...");
		List<PushUser> pushUserList = pushUserService.getPushUsers();// �����û�
		if (pushUserList != null && !pushUserList.isEmpty()) {
			String dataId = Constants.getDataId();
			String time = Constants.getNowBeiJingTime();
			List<PushData> pushDatas = new ArrayList<PushData>();
			IQ notificationIQ = createNotificationIQ(dataId, apiKey,
					sendUsername, sendName, message, "0", "", uri, time);

			for (PushUser pushUser : pushUserList) {
				String recvUsername = pushUser.getUsername();
				String recvName = pushUser.getName();
				PushData pushData = new PushData(dataId, sendUsername,
						sendName, recvUsername, recvName, message, "0", "",
						uri, Constants.TOOL_WEB_ALL, time, time);
				ClientSession recvSession = sessionManager
						.getSession(recvUsername);
				if (recvSession != null
						&& recvSession.getPresence().isAvailable()
						&& presenceManager.isAvailable(pushUser)) {
					pushData.setStatus(Constants.STATUS_ALREADY_SEND);
					notificationIQ.setTo(recvSession.getAddress());
					recvSession.deliver(notificationIQ);
				} else {
					pushData.setStatus(Constants.STATUS_NOT_YET_SEND);
				}
				pushDatas.add(pushData);
			}
			pushDataService.createPushDatas(pushDatas);
		}
	}

	/**
	 * ���͸����������û�
	 * 
	 * @param apiKey
	 * @param sendName
	 * @param message
	 * @param uri
	 */
	public void sendToOnlineUsers(String apiKey, String sendUsername,
			String sendName, String message, String uri) {
		log.debug("sendToOnlineUsers()...");
		Collection<ClientSession> recvSessions = sessionManager.getSessions();
		if (recvSessions != null && !recvSessions.isEmpty()) {
			String dataId = Constants.getDataId();
			String time = Constants.getNowBeiJingTime();
			List<PushData> pushDatas = new ArrayList<PushData>();
			IQ notificationIQ = createNotificationIQ(dataId, apiKey,
					sendUsername, sendName, message, "0", "", uri, time);
			for (ClientSession recvSession : recvSessions) {
				String recvUsername;
				try {
					recvUsername = recvSession.getUsername();
					String recvName = pushUserService.getPushUserByUsername(
							recvUsername).getName();
					PushData pushData = new PushData(dataId, sendUsername,
							sendName, recvUsername, recvName, message, "0", "",
							uri, Constants.TOOL_WEB_ONLINE, time, time);
					if (recvSession.getPresence().isAvailable()) {
						pushData.setStatus(Constants.STATUS_ALREADY_SEND);
						notificationIQ.setTo(recvSession.getAddress());
						recvSession.deliver(notificationIQ);
					} else {
						pushData.setStatus(Constants.STATUS_NOT_YET_SEND);
					}
					pushDatas.add(pushData);
				} catch (UserNotFoundException e) {
					e.printStackTrace();
				}
			}
			pushDataService.createPushDatas(pushDatas);
		}
	}

	/**
	 * ��web���͸�ָ���û�
	 * 
	 * @param apiKey
	 * @param sendName
	 * @param recvUsernames
	 * @param message
	 * @param uri
	 */
	public void webSendToSomeUsers(String apiKey, String sendUsername,
			String sendName, String recvUsernames, String message, String uri) {
		log.debug("sendToSomeUsers()...");
		String[] username = recvUsernames.split(" ");
		if (username != null) {
			List<PushUser> pushUserList = pushUserService.getPushUsers();// �����û�
			List<String> allUsername = new ArrayList<String>();
			if (username.length > 0 && pushUserList != null
					&& !pushUserList.isEmpty()) {
				username = Constants.delRepeatStr(username);// ���˵��ظ����ַ�
				for (PushUser user : pushUserList) {
					allUsername.add(user.getUsername());
				}
				String dataId = Constants.getDataId();
				String time = Constants.getNowBeiJingTime();
				List<PushData> pushDatas = new ArrayList<PushData>();
				IQ notificationIQ = createNotificationIQ(dataId, apiKey,
						sendUsername, sendName, message, "0", "", uri, time);
				for (int i = 0; i < username.length; i++) {
					if (!username[i].trim().equals("")
							&& allUsername.contains(username[i])) {
						String recvName = pushUserService
								.getPushUserByUsername(username[i]).getName();
						PushData pushData = new PushData(dataId, sendUsername,
								sendName, username[i], recvName, message, "0",
								"", uri, Constants.TOOL_WEB_SPECIFIED, time,
								time);
						ClientSession recvSession = sessionManager
								.getSession(username[i]);
						if (recvSession != null
								&& recvSession.getPresence().isAvailable()
								&& presenceManager.isAvailable(pushUserService
										.getPushUserByUsername(username[i]))) {
							pushData.setStatus(Constants.STATUS_ALREADY_SEND);
							notificationIQ.setTo(recvSession.getAddress());
							recvSession.deliver(notificationIQ);
						} else {
							pushData.setStatus(Constants.STATUS_NOT_YET_SEND);
						}
						pushDatas.add(pushData);
					}
				}
				pushDataService.createPushDatas(pushDatas);
			}
		}
	}

	/**
	 * �ӿͻ��˷��͸�ָ���û�
	 * 
	 * @param apiKey
	 * @param sendName
	 * @param recvUsernames
	 * @param message
	 * @param uri
	 * @param tool
	 */
	public void clientSendToSomeUsers(String dataId, String have_image,
			String gps, String apiKey, String sendUsername, String sendName,
			String recvUsernames, String message, String uri, String time) {
		log.debug("sendToSomeUsers()...");
		String[] username = recvUsernames.split(" ");
		if (username != null) {
			List<PushUser> pushUserList = pushUserService.getPushUsers();// �����û�
			List<String> allUsername = new ArrayList<String>();
			if (username.length > 0 && pushUserList != null
					&& !pushUserList.isEmpty()) {
				username = Constants.delRepeatStr(username);// ���˵��ظ����ַ�
				for (PushUser user : pushUserList) {
					allUsername.add(user.getUsername());
				}
				List<PushData> pushDatas = new ArrayList<PushData>();
				IQ notificationIQ = createNotificationIQ(dataId, apiKey,
						sendUsername, sendName, message, have_image, gps, uri,
						time);
				for (int i = 0; i < username.length; i++) {
					if (!username[i].trim().equals("")
							&& allUsername.contains(username[i])) {
						String recvName = pushUserService
								.getPushUserByUsername(username[i]).getName();
						PushData pushData = new PushData(dataId, sendUsername,
								sendName, username[i], recvName, message,
								have_image, gps, uri,
								Constants.TOOL_CLIENT_SPECIFIED, time, time);
						ClientSession recvSession = sessionManager
								.getSession(username[i]);
						if (recvSession != null
								&& recvSession.getPresence().isAvailable()
								&& presenceManager.isAvailable(pushUserService
										.getPushUserByUsername(username[i]))) {
							pushData.setStatus(Constants.STATUS_ALREADY_SEND);
							notificationIQ.setTo(recvSession.getAddress());
							recvSession.deliver(notificationIQ);
						} else {
							pushData.setStatus(Constants.STATUS_NOT_YET_SEND);
						}
						pushDatas.add(pushData);
					}
				}
				pushDataService.createPushDatas(pushDatas);
			}
		}
	}

	/**
	 * ����������Ϣ
	 * 
	 * @param pushData
	 */
	public void sendOfflineNotification(PushData pushData) {
		log.debug("sendOfflineNotification()...");
		String apiKey = Config.getString("apiKey", "");
		IQ notificationIQ = createNotificationIQ(pushData.getDataId(), apiKey,
				pushData.getSendUsername(), pushData.getSendName(),
				pushData.getMessage(), pushData.getHave_image(),
				pushData.getGps(), pushData.getUri(), pushData.getCreatedDate());
		ClientSession session = sessionManager.getSession(pushData
				.getRecvUsername());
		if (session != null && session.getPresence().isAvailable()) {
			notificationIQ.setTo(session.getAddress());
			session.deliver(notificationIQ);
			try {
				pushData.setStatus(Constants.STATUS_ALREADY_SEND);
				pushData.setUpdatedDate(Constants.getNowBeiJingTime());
				pushDataService.updatePushData(pushData);
			} catch (Exception e) {
				log.warn(" update notification status failure !");
			}
		}
	}

	/**
	 * ���ͱ������ߵ���Ϣ
	 * 
	 * @param session
	 */
	public void sendCloseSessionNotification(ClientSession session) {
		log.debug("sendCloseSessionNotification()...");
		String apiKey = Config.getString("apiKey", "");
		IQ notificationIQ = createNotificationIQ("to_close", apiKey,
				"PushServer", "Push������", "����ʺ��ڱ𴦵�¼���㱻�����ߣ�", "", "", "",
				Constants.getNowBeiJingTime());
		notificationIQ.setTo(session.getAddress());
		session.deliver(notificationIQ);
	}

	/**
	 * ����һ��IQ��
	 */
	public IQ createNotificationIQ(String dataId, String apiKey,
			String sendUsername, String sendName, String message,
			String haveImage, String gps, String uri, String time) {
		Element notification = DocumentHelper.createElement(QName.get(
				"notification", NOTIFICATION_NAMESPACE));
		notification.addElement("dataId").setText(dataId);
		notification.addElement("apiKey").setText(apiKey);
		notification.addElement("sendUsername").setText(sendUsername);
		notification.addElement("sendName").setText(sendName);
		notification.addElement("message").setText(message);
		notification.addElement("haveImage").setText(haveImage);
		notification.addElement("gps").setText(gps);
		notification.addElement("uri").setText(uri);
		notification.addElement("time").setText(time);

		IQ iq = new IQ();
		iq.setType(IQ.Type.set);
		iq.setChildElement(notification);

		return iq;
	}

}
